1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2004-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: HTTPOutputStream.java,v 1.2 2005/04/04 15:08:53 tanderson Exp $
44 */
45 package org.exolab.jms.net.http;
46
47 import java.io.IOException;
48 import java.io.OutputStream;
49 import java.net.HttpURLConnection;
50 import java.net.URL;
51 import java.net.URLConnection;
52
53 import org.apache.commons.logging.Log;
54 import org.apache.commons.logging.LogFactory;
55
56
57 /***
58 * Writes to an {@link URLConnection}.
59 *
60 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
61 * @version $Revision: 1.2 $ $Date: 2005/04/04 15:08:53 $
62 */
63 class HTTPOutputStream extends OutputStream {
64
65 /***
66 * The connection identifier.
67 */
68 private final String _id;
69
70 /***
71 * The tunnel servlet URL.
72 */
73 private final URL _url;
74
75 /***
76 * The connection information.
77 */
78 private final HTTPRequestInfo _info;
79
80 /***
81 * The local data buffer.
82 */
83 private final byte[] _data;
84
85 /***
86 * The current index into <code>_data</code>.
87 */
88 private int _index;
89
90 /***
91 * The logger.
92 */
93 private static final Log _log = LogFactory.getLog(HTTPOutputStream.class);
94
95
96 /***
97 * Construct a new <code>HTTPOutputStream</code>.
98 *
99 * @param id the connection identifier
100 * @param url the URL to connect to
101 * @param size the size of the buffer
102 * @param info the connection information
103 */
104 public HTTPOutputStream(String id, URL url, int size, HTTPRequestInfo info) {
105 _id = id;
106 _url = url;
107 _data = new byte[size];
108 _info = info;
109 }
110
111 /***
112 * Flushes this output stream and forces any buffered output bytes to be
113 * written out.
114 *
115 * @throws IOException if an I/O error occurs
116 */
117 public void flush() throws IOException {
118 while (_index > 0) {
119 doWrite();
120 }
121 }
122
123 /***
124 * Writes length bytes from the specified byte array starting at offset to
125 * this output stream.
126 *
127 * @param buffer the data to write
128 * @param offset the start offset in the data
129 * @param length the number of bytes to write
130 * @throws IOException if an I/O error occurs
131 */
132 public void write(byte[] buffer, int offset, int length)
133 throws IOException {
134
135 int space = _data.length - _index;
136 if (space >= length) {
137
138 System.arraycopy(buffer, offset, _data, _index, length);
139 _index += length;
140 } else {
141 flush();
142 doWrite(buffer, offset, length);
143 }
144 }
145
146 /***
147 * Writes the specified byte to this output stream.
148 *
149 * @param value the byte value
150 * @throws IOException if an I/O error occurs
151 */
152 public void write(int value) throws IOException {
153 while (_index >= _data.length) {
154 flush();
155 }
156 _data[_index++] = (byte) value;
157 }
158
159 /***
160 * Writes from the local data buffer to the underlying connection.
161 *
162 * @throws IOException if an I/O error occurs
163 */
164 private void doWrite() throws IOException {
165 try {
166 doWrite(_data, 0, _index);
167 _index = 0;
168 } catch (IOException exception) {
169 _log.debug(exception, exception);
170 throw exception;
171 }
172 }
173
174 /***
175 * Writes length bytes from the specified byte array starting at offset to
176 * the underlying connection.
177 *
178 * @param buffer the data to write
179 * @param offset the start offset in the data
180 * @param length the number of bytes to write
181 * @throws IOException if an I/O error occurs
182 */
183 private void doWrite(byte[] buffer, int offset, int length)
184 throws IOException {
185
186 HttpURLConnection connection =
187 TunnelHelper.create(_url, _id, "write", _info);
188 connection.setDoOutput(true);
189 OutputStream out = connection.getOutputStream();
190 out.write(buffer, offset, length);
191 out.close();
192 if (_log.isDebugEnabled()) {
193 _log.debug("doWrite(length=" + length + "), [id=" + _id + "]");
194 }
195
196 if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
197 throw new IOException(connection.getResponseCode() + " "
198 + connection.getResponseMessage());
199 }
200
201 }
202
203 }